# -*- coding: utf-8 -*-
"""
文件名解析器
负责解析各种格式的视频文件名并提取关键信息
"""
import os
import re
from typing import List

from config import VideoConfig

from .models import VideoInfo, VideoType, VideoSubType


class VideoNameParser:
    """视频文件名解析器"""

    def __init__(self):
        self.config = VideoConfig()
        self.patterns = self.config.get_all_patterns()

    def parse(self, filename: str) -> VideoInfo:
        """
        解析视频文件名
        
        :param filename: 文件名
        :return: VideoInfo 对象
        """
        video_info = VideoInfo(original_filename=filename, video_type=VideoType.UNKNOWN, core_id="")

        cleaned_filename = self._clean_filename(filename)
        if cleaned_filename != filename:
            video_info.is_dirty = True
            video_info.error_reason = f"文件名包含脏数据，已清理: {filename} -> {cleaned_filename}"

        # 核心逻辑：先提取后缀和核心番号
        self._extract_core_id_and_flags(cleaned_filename, video_info)

        core_id = video_info.core_id

        # 严格按照优先级进行分类
        if self._parse_fc2(core_id, video_info):
            return video_info
        elif self._parse_uncensored_nk_format(core_id, video_info):
            return video_info
        elif self._parse_uncensored_prefix(core_id, video_info):
            return video_info
        elif self._parse_uncensored_numeric(core_id, video_info):
            return video_info
        elif self._parse_censored(core_id, video_info):
            return video_info
        else:
            video_info.is_dirty = True
            video_info.error_reason = f"无法识别的核心番号格式: {core_id}"
            return video_info

    def _clean_filename(self, filename: str) -> str:
        """清理文件名中的已知脏数据"""
        return re.sub(r'FC2--', 'FC2-', filename)

    def _extract_core_id_and_flags(self, filename: str, video_info: VideoInfo) -> None:
        """
        从文件名中提取核心番号、后缀标志和扩展名
        """
        basename, extension = os.path.splitext(filename)
        video_info.extension = extension

        # 使用正则表达式保留分隔符进行分割
        # 先统一处理空格等问题
        basename = basename.strip()
        parts = [p for p in re.split('([_-])', basename) if p]

        # 从后向前解析后缀
        remaining_parts = self._parse_suffixes_from_parts(parts, video_info)

        # 重组剩余部分为核心番号
        video_info.core_id = "".join(remaining_parts).strip()

    def _parse_suffixes_from_parts(self, parts: List[str], video_info: VideoInfo) -> List[str]:
        """从分割后的部分列表的末尾开始解析已知后缀"""

        temp_parts = list(parts)

        while temp_parts:
            last_part = temp_parts[-1].upper()

            # 检查4K标识
            if last_part == self.config.FOURK_MARKER:
                video_info.has_4k = True
                temp_parts.pop()  # pop content
                if temp_parts and temp_parts[-1] in "-_": temp_parts.pop()  # pop separator
                continue

            # 检查流出标识
            if last_part == self.config.LEAK_MARKER:
                video_info.has_leak = True
                temp_parts.pop()
                if temp_parts and temp_parts[-1] in "-_": temp_parts.pop()
                continue

            # 检查字幕标识 (-C)
            if last_part == 'C':
                video_info.has_subtitle = True
                temp_parts.pop()
                if temp_parts and temp_parts[-1] in "-_": temp_parts.pop()
                continue

            # 检查分段标识 (CD1, CD2, etc.)
            segment_match = re.match(r'CD(\d+)', last_part, re.IGNORECASE)
            if segment_match:
                video_info.segment_number = segment_match.group(1)
                temp_parts.pop()
                if temp_parts and temp_parts[-1] in "-_": temp_parts.pop()
                continue

            # 如果当前部分不是任何已知后缀，则停止解析
            break

        return temp_parts

    """解析FC2格式番号"""

    def _parse_fc2(self, core_id: str, video_info: VideoInfo) -> bool:
        """解析FC2格式番号"""
        match = re.match(r'^FC2-(\d+)$', core_id, re.IGNORECASE)
        if not match:
            return False

        video_info.video_type = VideoType.FC2
        video_info.prefix = "FC2"
        video_info.number = match.group(1)
        return True

    """解析N/K特殊无码格式番号"""

    def _parse_uncensored_nk_format(self, core_id: str, video_info: VideoInfo) -> bool:
        """解析N/K特殊无码格式番号"""
        match = re.match(r'^([NK])(\d{4,})$', core_id, re.IGNORECASE)
        if not match:
            return False

        prefix = match.group(1).upper()
        number = match.group(2)

        video_info.video_type = VideoType.UNCENSORED
        video_info.video_subtype = VideoSubType.PREFIX
        video_info.prefix = prefix
        video_info.number = number
        return True

    def _parse_uncensored_prefix(self, core_id: str, video_info: VideoInfo) -> bool:
        """解析无码特殊前缀格式番号"""
        match = re.match(f"^(" + self.patterns['uncensored_prefix'] + r")-(\d+)$", core_id, re.IGNORECASE)
        if not match:
            return False

        video_info.video_type = VideoType.UNCENSORED
        video_info.video_subtype = VideoSubType.PREFIX
        video_info.prefix = match.group(1).upper()
        video_info.number = match.group(2)
        return True

    def _parse_uncensored_numeric(self, core_id: str, video_info: VideoInfo) -> bool:
        """解析无码纯数字格式番号"""
        match = re.match(r'^(\d+)[-_](\d+)$', core_id, re.IGNORECASE)
        if not match:
            return False

        video_info.video_type = VideoType.UNCENSORED
        video_info.video_subtype = VideoSubType.NUMERIC
        video_info.prefix = match.group(1)  # 第一个数字
        video_info.number = match.group(2)  # 第二个数字
        return True

    def _parse_censored(self, core_id: str, video_info: VideoInfo) -> bool:
        """解析有码格式番号"""
        match = re.match(r'^([a-zA-Z]+)-(\d+)$', core_id, re.IGNORECASE)
        if not match:
            return False

        video_info.video_type = VideoType.CENSORED
        video_info.prefix = match.group(1).upper()
        video_info.number = match.group(2)
        return True

    def add_uncensored_prefix(self, prefix: str) -> None:
        """添加新的无码特殊前缀"""
        self.config.add_uncensored_prefix(prefix.upper())
        self.patterns = self.config.get_all_patterns()
